<?php
/**
 * Created by PhpStorm.
 * User: yangjiaming
 * Date: 2018/2/6
 * Time: 11:22
 */

namespace Halo\Data;

use Medoo\Medoo;
class DAO
{
    private $adapter;
    public function __construct($adapter)
    {
        $this->adapter = $adapter;
    }

    /***
     * 新增单条数据
     *作者:yjm
     *日期:2018/2/6
     * @param $params
     * @return int
     */
    public function create($params)
    {
        $table = $this->adapter->table();
        $this->prepareForCreate($params);
        $db = $this->getDb();
        $db->insert($table, $params);
        return $db->id();

    }

    /**
     * 更新单条数据
     * @author:yjm
     * @param $params
     * @return int
     */
    public function update($params)
    {
        $table = $this->adapter->table();
        $primaryId = $this->adapter->primaryIdParamName();
        $where[$primaryId] = $params[$primaryId];
        unset($params[$primaryId]);
        $db = $this->getDb();
        $result = $db->update($table, $params, $where);
        return  $result->rowCount();
    }

    /**
     * 获取单条数据
     * @author:yjm
     * @param $params
     * @param string $specified
     * @return array|bool|mixed
     */
    public function get($params, $specified = '*')
    {
        $db = $this->getDb();
        $table = $this->adapter->table();
        $condition = $this->paramsToCondition($params);

        return $db->get($table, $specified, $condition);
    }

    /**
     * 获取列表数据
     * @author:yjm
     * @param $params
     * @param string $specified 查询字段
     * @param array $pager 分页
     * @param array $sort 排序
     * @return array count总数 data 数据
     */
    public function read($params, $specified = '*', $pager = [], $sort = [])
    {
        if(empty($specified)) {
            $specified = '*';
        }
        $db = $this->getDb();
        $table = $this->adapter->table();
        $condition = $this->paramsToCondition($params);
        $count = $db->count($table, '*', $condition);

        $stat = array('count' => $count);
        $result = [];
        if ($count > 0) {
            $pager = $this->getPage($pager);
            $sort = $this->getSort($sort);
            $result = $db->select($table, $specified, $condition, array_merge($pager, $sort));
        }
        $retResult = array(
            'statistic' => $stat,
            'data' => $result
        );

        return $retResult;

    }

    /**
     * 批量更新
     * @author:yjm
     * @param $toArray array update数据
     * @param $query array where条件
     * @return int
     */
    public function updateByQuery($toArray, $query)
    {
        $table = $this->adapter->table();
        $db = $this->getDb();
        $condition = $this->paramsToCondition($query);
        $result = $db->update($table, $toArray, $condition);
        return  $result->rowCount();
    }
    /**
     * 获取条数
     * @author:yjm
     * @param $params
     * @return mixed
     */
    public function count($params)
    {
        $db = $this->getDb();
        $table = $this->adapter->table();
        $condition = $this->paramsToCondition($params);
        $count = $db->count($table, '*', $condition);
        return $count;
    }
    /**
     * 处理分页
     * @author:yjm
     * @param $pager
     * @return array
     */
    public function getPage($pager)
    {
        if (!empty($pager)) {
            if(!isset($pager['page_size'])) $pager['page_size'] = $pager['limit'];
            if (!isset($pager['page']) || $pager['page'] < 1) {
                $pager['page'] = 1;
            }
            $offset = ($pager['page'] - 1) * $pager['page_size'];
            $limit = $pager['page_size'];
            $pages = [$offset, $limit];
            return ['LIMIT' => $pages];
        }
        return [];
    }

    /**
     * 处理排序
     * @author:yjm
     * @param $sort
     * @return array
     */
    public function getSort($sort)
    {
        if(!empty($sort)) {
            return ['ORDER' => $sort];
        }
        return [];
    }
    /**
     * 查询where参数转化
     * @author:yjm
     * @param $params
     * @return array
     */
    public function paramsToCondition(&$params)
    {
        $bindParams = array();
        $fields = $params;
        $this->adapter->softDeleted() && $fields[$this->adapter->softDeleted()] = 0;
        foreach ($fields as $f => $v) {
            $operation = 'eq';
            $value = $v;
            if (is_array($value)) {
                $operation = $value['operation'];
                $value = $v['value'];
            }
            $this->appendOperation($bindParams, $f, $operation, $value);
        }

        return $bindParams;
    }

    /**
     * 处理where
     * @author:yjm
     * @param $bindParams 条件
     * @param $field 字段
     * @param $operation 类型
     * @param $value 值
     */
    private function appendOperation(&$bindParams, $field, $operation, $value)
    {
        if ($operation == 'in') {
            $bindParams[$field] = $value;
        } else if ($operation == 'no_in') {
            $bindParams[$field.'[!]'] = $value;
        } else if ($operation == 'range') {
            $bindParams[$field.'[<>]'] = $value;
        } else if($operation == 'no_range') {
            $bindParams[$field.'[><]'] = $value;
        } else if ($operation == 'interval') {

        } else if ($operation == 'prefix') {
            $bindParams[$field.'[~]'] = $value;
        } else if($operation == 'not_null'){
            $bindParams[$field.'[!]'] = null;
        } else if($operation == 'is_null'){
            $bindParams[$field] = null;
        } else if($operation == 'or') {
            $bindParams['OR'] = $value;
        } else {
            $operationMap = array(
                'lt' => '<',
                'le' => '<=',
                'gt' => '>',
                'ge' => '>=',
                'eq' => '=',
                'neq' => '!',
            );

            if (isset($operationMap[$operation])) {
                $bindParams[$field.'['.$operationMap[$operation].']'] = $value;
            }
        }
    }
    /**
     * 添加默认参数
     * @author:yjm
     * @param $params
     * @return array
     */
    public function prepareForCreate(&$params)
    {
        $defaultValues = $this->adapter->defaultParamValues();
        if (!empty($defaultValues)) {
            foreach ($defaultValues as $k => $v) {
                if (!isset($params[$k])) {
                    $params[$k] = $v;
                }
            }
        }
        $time = time();
        if ($createField = $this->adapter->autoCreateTimestamp()) {
            if(!isset($params[$createField]))
                $params[$createField] = $time;
        }
        if ($updateField = $this->adapter->autoUpdateTimestamp()) {
            $params[$updateField] = $time;
        }

        if ($deletedField = $this->adapter->softDeleted()) {
            $params[$deletedField] = 0;
        }

        return $params;
    }

    /**
     * 返回数据库实例
     * @author:yjm
     * @return Medoo
     */
    public function getDb()
    {
        $adapter = $this->adapter;
        $db_config = ($adapter->dbConfig()) ? $adapter->dbConfig() : [];
        $config = [
            'host' => $db_config?$db_config['host']:DB_HOST,
            'port' => $db_config?$db_config['port']:DB_PORT,
            'user' => $db_config?$db_config['user']:DB_USER,
            'pass' => $db_config?$db_config['pass']:DB_PASS,
            'dbname' => $adapter->database()?$adapter->database():DB_NAME
        ];
        $db['database_type'] = DB_TYPE;
        $db['database_name'] = $config['dbname'];
        $db['server'] = $config['host'];
        $db['username'] = $config['user'];
        $db['password'] = $config['pass'];
        $db['port'] = $config['port'];
        $database = new Medoo($db);
        return $database;
    }
}